package net.lulihu.pangolin.headless.common.util;

import lombok.extern.slf4j.Slf4j;
import net.lulihu.pangolin.headless.common.functional.Consumption;
import net.lulihu.pangolin.headless.common.functional.ConsumptionResult;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * 读写锁工具
 */
@Slf4j
public class ReadWriteLockKit {

    // 读写锁
    private final Lock readLock;
    private final Lock writeLock;


    public ReadWriteLockKit() {
        this(false);
    }

    /**
     * @param fair true为公平锁 反之为竞争锁
     */
    public ReadWriteLockKit(boolean fair) {
        ReadWriteLock globalLock = new ReentrantReadWriteLock(fair);
        this.readLock = globalLock.readLock();
        this.writeLock = globalLock.writeLock();
    }


    /**
     * 有返回值执行读锁方法
     *
     * @param consumption 有返回值的执行表达式
     * @param <T>         返回值
     * @return 指定的返回结果
     */
    public <T> T exeReadLockMethod(ConsumptionResult<T> consumption) {
        try {
            readLock.lock();//先加读锁
            // 执行目标方法
            return consumption.accept();
        } finally {
            readLock.unlock();//解锁
        }
    }

    /**
     * 有返回值执行写锁方法
     *
     * @param consumption 有返回值的执行表达式
     * @param <T>         返回值
     * @return 指定的返回结果
     */
    public <T> T exeWriteLockMethod(ConsumptionResult<T> consumption) {
        try {
            writeLock.lock();//先加写锁
            // 执行目标方法
            return consumption.accept();
        } finally {
            writeLock.unlock();//解锁
        }
    }


    /**
     * 无返回值执行写锁方法
     *
     * @param consumption 无返回值的执行表达式
     */
    public void exeWriteLockMethod(Consumption consumption) {
        try {
            writeLock.lock();//先加写锁
            // 执行目标方法
            consumption.accept();
        } finally {
            writeLock.unlock();//解锁
        }
    }

}
